package com.yanqu.road.server.manager.activity.camp;

import com.yanqu.road.entity.activity.camp.CampUnion;
import com.yanqu.road.entity.activity.camp.CampUnionMember;
import com.yanqu.road.server.manager.activity.fivehero.CrossFiveHeroMgr;
import com.yanqu.road.server.manager.activity.tonbing.CrossTonBingMgr;
import com.yanqu.road.server.manager.activity.tongbing.CrossTongBingMgr;
import com.yanqu.road.utils.RandomHelper;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author : Cxp
 * @Time : 2025-02-17
 * @Description : 阵营分配
 */

public class Camp {

    private static CampApi campApi;

    private static eCampActivityType type;

    private static final RandomHelper randomHelper = new RandomHelper();

    public static void divide(List<CampUnion> unions, List<Integer> secondMatchRanges, List<Long> abilityParams, int campNum,
                              int campUnionNum, int activityId, int groupId, eCampActivityType eCampActivityType) {
        type = eCampActivityType;
        campApi = getCampApiByType(activityId, groupId);
        if (campApi == null) {
            return;
        }

        /*
         * 对1-XXX名商会进行战力压缩
         * 1	商会总战力 = 商会所有成员的战力相加
         * 2	商会成员战力计算方式
         * 	1	取玩家历史最高赚钱 / 5，得到5个队伍的平均赚钱
         * 	2	根据5个队伍平均赚钱，配合战力转换公式，得到5个队伍能够提供的战力
         * 	3	最后再根据5个队伍的兵力 * 5，得到单名玩家能够提供的兵力
         */
        List<CampUnion> mergeUnions = new ArrayList<>();
        for (int i = 0; i < unions.size(); i++) {
            CampUnion campUnion = unions.get(i);
            BigDecimal totalAbility = BigDecimal.ZERO;
            if (i < campNum) { // 前N名提前处理
                mergeUnions.add(campUnion);
            }

            calculate(abilityParams, campUnion.getCampMemberMap(), totalAbility, campUnion);
        }

        unions = campApi.resort(unions);

        for (int i = 0; i < unions.size(); i++) {
            CampUnion union = unions.get(i);
            union.setCompressRank(i + 1);
            if (union.getOldRank() > campNum) {
                mergeUnions.add(union);
            }
        }

        Map<Integer, BigDecimal> campAbilityMap = new ConcurrentHashMap<>();
        Map<Integer, List<String>> campUnionMap = new ConcurrentHashMap<>();

        List<Integer> campNumberList = new ArrayList<>();
        for (int campId = 1; campId <= campNum; campId++) {
            campNumberList.add(campId);
            campAbilityMap.put(campId, BigDecimal.ZERO);
        }
        Collections.shuffle(campNumberList);
        for (int i = 0; i < campNum; i++) {
            putJoinUnionIntoCamp(mergeUnions, campAbilityMap, campUnionMap, i + 1, campNumberList.get(i));
        }

        // 以统兵为例 4-30
        int startRank = campNum + 1;
        int endRank = secondMatchRanges.get(1);
        int secondMatchTimes = (endRank - startRank + 1) / campNum;
        for (int i = 0; i < secondMatchTimes; i++) {
            for (int j = 0; j < campNum; j++) {
                int rank = startRank + i * campNum + j;
                putJoinUnionIntoMinAbilityCamp(mergeUnions, campAbilityMap, campUnionMap, rank);
            }
        }

        // 以统兵为例 31-240 遍历剩余商会按加入最低的分配
        for (int i = endRank; i < mergeUnions.size(); i++) {
            int rank = i + 1;
            // 按 value 升序排序并提取 key 到 List
            List<Integer> campIdList = getCampIdList(campAbilityMap, campUnionMap);
            for (Integer joinCampId : campIdList) {
                // 跳过已经分配满的阵营
                if (campUnionMap.get(joinCampId).size() >= campUnionNum) {
                    continue;
                }
                putJoinUnionIntoCamp(mergeUnions, campAbilityMap, campUnionMap, rank, joinCampId);
                break;
            }
        }
    }

    private static void calculate(List<Long> abilityParams, Map<Long, CampUnionMember> memberMap, BigDecimal totalAbility,
                                  CampUnion campUnion) {
        int unionMemberNum = memberMap.size();
        for (CampUnionMember joinMember : memberMap.values()) {
            long memberAbility = joinMember.getTopAbility();
            if (memberAbility <= 0) {
                continue;
            }
            long avgAbility = memberAbility / 5;
            if (avgAbility <= 0) {
                continue;
            }
            BigDecimal teamAbility = campApi.calcMemberCompressedAbility(avgAbility, unionMemberNum, abilityParams);
            teamAbility = teamAbility.multiply(BigDecimal.valueOf(5));
            totalAbility = totalAbility.add(teamAbility);
        }
        campUnion.setCompressedAbility(totalAbility);
    }

    private static List<Integer> getCampIdList(Map<Integer, BigDecimal> campAbilityMap, Map<Integer, List<String>> campUnionMap) {
        List<Integer> campIdList = new ArrayList<>(campAbilityMap.keySet());

        campIdList.sort((o1, o2) -> {
            //比较战力
            BigDecimal camp1Ability = campAbilityMap.get(o1);
            BigDecimal camp2Ability = campAbilityMap.get(o2);
            int compare = camp1Ability.compareTo(camp2Ability);
            if (compare == 0) {
                //较商会数量 低的在前
                int camp1UnionNum = campUnionMap.getOrDefault(o1, new ArrayList<>()).size();
                int camp2UnionNum = campUnionMap.getOrDefault(o2, new ArrayList<>()).size();
                compare = Integer.compare(camp1UnionNum, camp2UnionNum);
                if (compare == 0) {
                    //一样的就随机一下
                    compare = randomHelper.next(2);
                }
            }
            return compare;
        });

        return campIdList;
    }

    private static CampApi getCampApiByType(int activityId, int groupId) {
        switch (type) {
            case PEAK_TONGBING:
                return CrossTonBingMgr.getActivity(activityId);
            case TONGBING:
                return CrossTongBingMgr.getActivity(activityId, groupId);
            case FIVE_HERO:
                return CrossFiveHeroMgr.getFiveHeroActivity(activityId, groupId);
        }

        return null;
    }

    /**
     * 阵营数量一样时把商会放入最低战力阵营,不一样放入最少的
     *
     * @param unions         商会
     * @param campAbilityMap 压缩战力
     * @param campUnionMap   阵营商会
     * @param rank           排名
     */
    private static void putJoinUnionIntoMinAbilityCamp(List<CampUnion> unions, Map<Integer, BigDecimal> campAbilityMap, Map<Integer,
            List<String>> campUnionMap, int rank) {
        if (rank < 1 || rank > unions.size()) {
            return;
        }
        CampUnion union = unions.get(rank - 1);

        List<Integer> campIdList = new ArrayList<>(campAbilityMap.keySet());

        campIdList.sort((o1, o2) -> {
            //先比较商会数量 低的在前
            int camp1UnionNum = campUnionMap.getOrDefault(o1, new ArrayList<>()).size();
            int camp2UnionNum = campUnionMap.getOrDefault(o2, new ArrayList<>()).size();
            int compare = Integer.compare(camp1UnionNum, camp2UnionNum);
            if (compare == 0) {
                //商会数量一样的比较战力
                BigDecimal camp1Ability = campAbilityMap.get(o1);
                BigDecimal camp2Ability = campAbilityMap.get(o2);
                compare = camp1Ability.compareTo(camp2Ability);
                if (compare == 0) {
                    //战力一样的就随机一下
                    compare = randomHelper.next(2);
                }
            }
            return compare;
        });

        Integer joinCampId = campIdList.get(0);
        unionJoinCampMap(campAbilityMap, campUnionMap, joinCampId, union);
    }

    /**
     * 把商会放入指定阵营
     *
     * @param unions         商会
     * @param campAbilityMap 压缩战力
     * @param campUnionMap   阵营商会
     * @param rank           排名
     * @param campId         阵营ID
     */
    private static void putJoinUnionIntoCamp(List<CampUnion> unions, Map<Integer, BigDecimal> campAbilityMap, Map<Integer,
            List<String>> campUnionMap, int rank, int campId) {
        if (campId == 0) {
            return;
        }
        if (rank < 1 || rank > unions.size()) {
            return;
        }
        CampUnion union = unions.get(rank - 1);

        unionJoinCampMap(campAbilityMap, campUnionMap, campId, union);
    }

    private static void unionJoinCampMap(Map<Integer, BigDecimal> campAbilityMap, Map<Integer, List<String>> campUnionMap, int campId,
                                         CampUnion union) {
        BigDecimal campAbility = campAbilityMap.computeIfAbsent(campId, k -> BigDecimal.ZERO);
        campAbility = campAbility.add(union.getCompressedAbility());
        campAbilityMap.put(campId, campAbility);

        List<String> unionIds = campUnionMap.computeIfAbsent(campId, k -> new ArrayList<>());
        unionIds.add(union.getUnionUid());

        campApi.setUnionJoinCamp(union, campId);
    }
}
